﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using InfoPick.Lib.Telnet;
using InfoPick.Lib.Entity;
using System.Threading;
using InfoPick.Lib.Tools;
using System.Configuration;

namespace InfoPick.Lib.DataProvider
{
    public class TelnetProvider : DataProvider
    {
        private TelnetConnection tcMgw;
        private TelnetConnection tcMsc;
        private Server mgw;
        private Server msc;

        public TelnetProvider(Server mgw, Server msc)
        {
            this.mgw = mgw;
            this.msc = msc;
        }

        private volatile bool isEnd = false;

        public override bool Begin()
        {
            tcMgw = initTelnetConnection(mgw, ServerType.MGW);
            if (tcMgw == null)
            {
                Notice("MGW登陆失败！\r");
                return false;
            }
            tcMsc = initTelnetConnection(msc, ServerType.MSC);
            if (tcMsc == null)
            {
                Notice("MSC登陆失败！\r");
                return false;
            }

            //先握手一次，握手成功后才能执行命令
            if (handShake(tcMgw))
            {
                Notice("MGW握手成功！\r");
            }
            else
            {
                Notice("MGW握手失败！\r");
                return false;
            }
            if (handShake(tcMsc))
            {
                Notice("MSC握手成功！\r");
            }
            else
            {
                Notice("MSC握手失败！\r");
                return false;
            }


            //设置mgw为中文
            Notice("设置MGW的语言为中文！\r");
            if (setLangToZH(tcMgw))
            {
                Notice("设置语言成功！\r");
            }
            else
            {
                Notice("设置语言失败！\r");
                return false;
            }

            //定时握手线程
            Thread handshakeThreadMgw = new Thread(new ParameterizedThreadStart(handshakeThread));
            Thread handshakeThreadMsc = new Thread(new ParameterizedThreadStart(handshakeThread));
            handshakeThreadMgw.IsBackground = true;
            handshakeThreadMsc.IsBackground = true;
            handshakeThreadMgw.Start(tcMgw);
            handshakeThreadMsc.Start(tcMsc);

            return true;
        }


        private TelnetConnection initTelnetConnection(Server server,ServerType type)
        {
            Notice(string.Format("正在连接服务器 {0}\r", server.Address));
            TelnetConnection tc = new TelnetConnection(server.Address, server.Port);

            #region 连接服务器
            //telnet 防止连接不上导致的异常
            bool isConnected = false;
            const int times = 5; //重试次数
            for (int i = 0; i < times; i++)
            {
                try
                {
                    tc.Connect();
                    isConnected = true;
                    break;
                }
                //避免工作线程引发的unhandled exception 造成 程序 crash
                catch (Exception)
                {
                    if (tc.IsConnected)
                        tc.Close();

                    Notice("连接服务器失败，正在重试\r");
                    Thread.Sleep(100);
                    continue;
                }
            }
            if (!isConnected)
            {
                Notice("无法连接服务器\r");
                throw new Exception("无法连接服务器");
            }

            Notice("连接服务器成功，发送LGI命令\r");

            #endregion

            #region 登陆
            //login

            //try
            //{
            //    string res = tc.Login(server.UserName, server.Password);
            //    CmdSuccess("login", res);
            //}
            //catch (Exception e)
            //{
            //    Notice(e.Message);
            //    return null;
            //}

            ////打开工作目录，测试使用
            //if (server.UserName.ToLower() == "root")
            //    tc.ExecuteCmd("cd /home/shark/Telecom", new string[] { "#" });
            //else
            //    tc.ExecuteCmd("cd /home/shark/Telecom", new string[] { "$" });

            try
            {
                string cmd = string.Empty;
                switch(type)
                {
                    case ServerType.MGW:
                        cmd = string.Format("LGI:OP=\"{0}\",PWD=\"{1}\",IP=\"{2}\",PID={3},CLT=LMT;",
                            server.UserName, server.Password, server.Address, 2748);
                         //cmd = "cat mgwLogin.txt";
                        break;
                    case ServerType.MSC:
                        cmd = string.Format("LGI:OP=\"{0}\",PWD=\"{1}\",SER=\"{2}---操作维护系统\";",
                            server.UserName, server.Password, server.Address);
                         //cmd = "cat mscLogin.txt";
                        break;
                    default:
                        return null;
                }
                string res = tc.ExecuteCmd(cmd, new string[] { "---    END" });
                CmdSuccess("login", string.Format("{0}\r\n{1}\r\n", cmd, res));

                if (StringTools.CheckReturnCode(res))
                {
                    Notice("已登录\r");
                    return tc;
                }
                else
                {
                    Notice("登录失败\r");
                    return null;
                }
                

            }
            catch (Exception e)
            {
                Notice(e.Message+"\r");
                return null;
            }

            #endregion
        }

        public override void Complete()
        {
            isEnd = true;
            
        }

        private TelnetConnection getTC(string key)
        {
            if (dict[key].ToLower() == "mgw")
                return tcMgw;
            if (dict[key].ToLower() == "msc")
                return tcMsc;
            throw new Exception(string.Format("{0}的配置只能为‘mgw’或者‘msc’", key));
        }

        private static readonly int handShakeInterval = int.Parse(ConfigurationManager.AppSettings["HandShakeInterval"]);
        /// <summary>
        /// 需要与服务器每2分钟握手一次，否则掉线
        /// </summary>
        private void handshakeThread(object para)
        {
            TelnetConnection conn = para as TelnetConnection;
            if (conn != null)
            {
                const int step = 1000;
                int countDown = handShakeInterval;
                while (!isEnd)
                {
                    if (countDown <= 0)
                    {
                        //发送握手命令
                        Notice("发送定时握手命令\r");
                        if (!handShake(conn))
                        {
                            Notice("握手失败1次\r");
                            if (!handShake(conn))
                            {
                                Notice("握手失败2次\r");
                                if (!handShake(conn))
                                {
                                    Notice("握手失败3次，中断连接\r");
                                    isEnd = true;
                                    break;
                                }
                            }
                        }
                        //重置倒计时
                        countDown = handShakeInterval;
                    }
                    //每2分钟握手一次
                    Thread.Sleep(step);
                    countDown -= step;
                }

                if (conn.IsConnected)
                    conn.Close();
            }
        }

        private bool handShake(TelnetConnection conn)
        {
            try
            {
                string res = conn.ExecuteCmd("SHK HAND:;", new string[] { "---    END" });
                return StringTools.CheckReturnCode(res);
            }
            catch (System.Exception ex)
            {
                string message = string.Format("{0} : message:{1}\r\n{2}", DateTime.Now, ex.Message, ex.StackTrace);
                Log.Log.WriteLog(message);
                Notice(string.Format("握手发生异常\r"));
                return false;
            }
           

        }

        private bool setLangToZH(TelnetConnection conn)
        {
            try
            {
                string res = conn.ExecuteCmd("SET LANG:LANG=CH;", new string[] { "---    END" });
                return StringTools.CheckReturnCode(res);
            }
            catch (System.Exception ex)
            {
                string message = string.Format("{0} : message:{1}\r\n{2}", DateTime.Now, ex.Message, ex.StackTrace);
                Log.Log.WriteLog(message);
                Notice(string.Format("设置语言发生异常\r"));
                return false;
            }


        }

        public override string GetTdmiuList()
        {
            string cmd = "LST TDMIU:;";
            //cmd = "cat 'LST TDMIU.txt'";

            //包含E32和S2L所以有2个"结果个数"
            string res = getTC("TDMIU").ExecuteCmd(cmd, new string[] { "结果个数", "结果个数", "---    END" });
            CmdSuccess(cmd, res);
            if (!StringTools.CheckReturnCode(res))
            {
                throw new Exception(string.Format("{0}执行失败，RETCODE不为0\r", cmd));
            }
            return res;
        }

        public override string GetE32List()
        {
            string cmd = "LST BRD: LM=BTBN, BT=E32;";
            //cmd = "cat 'LST BRD(E32).txt'";
            string res = getTC("E32").ExecuteCmd(cmd, new string[] { "结果个数", "---    END" });
            CmdSuccess(cmd, res);
            if (!StringTools.CheckReturnCode(res))
            {
                throw new Exception(string.Format("{0}执行失败，RETCODE不为0\r", cmd));
            }
            return res;
        }

        public override string GetS2lList()
        {
            string cmd = "LST BRD: LM=BTBN, BT=S2L;";
            //cmd = "cat 'LST BRD(S2L).txt'";
            string res = getTC("S2L").ExecuteCmd(cmd, new string[] { "结果个数", "---    END" });
            CmdSuccess(cmd, res);
            if (!StringTools.CheckReturnCode(res))
            {
                throw new Exception(string.Format("{0}执行失败，RETCODE不为0\r", cmd));
            }
            return res;

        }

        public override string GetEpiList()
        {
            string cmd = "LST BRD: BT=WEPI;";
            //cmd = "cat 'LST BRD(EPI).txt'";
            string wepi = getTC("EPI").ExecuteCmd(cmd, new string[] { "结果个数", "---    END" });
            CmdSuccess(cmd, wepi);
            if (!StringTools.CheckReturnCode(wepi))
            {
                throw new Exception(string.Format("{0}执行失败，RETCODE不为0\r", cmd));
            }
            return wepi;
        }

        public override string GetCsuList()
        {
            string cmd = "LST BRD: BT=WCSU;";
            //cmd = "cat 'LST BRD(CSU).txt'";
            string wscu = getTC("CSU").ExecuteCmd(cmd, new string[] { "结果个数", "---    END" });
            CmdSuccess(cmd, wscu);
            if (!StringTools.CheckReturnCode(wscu))
            {
                throw new Exception(string.Format("{0}执行失败，RETCODE不为0\r", cmd));
            }
            return wscu;

        }

        public override string GetN7LNKALLList()
        {
            string cmd = "LST N7LNK: LTP=LOCAL;";
            //cmd = "cat 'LST N7LNK11.txt'";
            string res = getTC("N7LNKALL").ExecuteCmd(cmd, new string[] { "结果个数", "结果个数", "---    END" });
            CmdSuccess(cmd, res);
            if (!StringTools.CheckReturnCode(res))
            {
                throw new Exception(string.Format("{0}执行失败，RETCODE不为0\r", cmd));
            }
            return res;
        }

        public override string GetAIETKCList()
        {
            string cmd = "LST AIETKC: MODE=BYCIC;";
            //cmd = "cat 'LST AIETKC.txt'";
            string res = getTC("AIETKC").ExecuteCmd(cmd, new string[] { "结果个数", "---    END" });
            CmdSuccess(cmd, res);
            if (!StringTools.CheckReturnCode(res))
            {
                throw new Exception(string.Format("{0}执行失败，RETCODE不为0\r", cmd));
            }
            return res;

        }

        public override string GetN7TKCList()
        {
            string cmd = "LST N7TKC: QR=LOCAL;";
            //cmd = "cat 'LST N7TKC.txt'";
            string res = getTC("N7TKC").ExecuteCmd(cmd, new string[] { "结果个数", "---    END" });
            CmdSuccess(cmd, res);
            if (!StringTools.CheckReturnCode(res))
            {
                throw new Exception(string.Format("{0}执行失败，RETCODE不为0\r", cmd));
            }
            return res;

        }

        public override string GetAIETGList()
        {
            string cmd = "LST AIETG:;";
            //cmd = "cat 'LST AIETG.txt'";
            string res = getTC("AIETG").ExecuteCmd(cmd, new string[] { "结果个数", "---    END" });
            CmdSuccess(cmd, res);
            if (!StringTools.CheckReturnCode(res))
            {
                throw new Exception(string.Format("{0}执行失败，RETCODE不为0\r", cmd));
            }
            return res;
        }

       

        public override string GetN7LNKList()
        {
            string cmd = "LST N7LNK:;";
            //cmd = "cat 'LST N7LNK.txt'";
            string res = getTC("N7LNK").ExecuteCmd(cmd, new string[] { "结果个数", "---    END" });
            CmdSuccess(cmd, res);
            if (!StringTools.CheckReturnCode(res))
            {
                throw new Exception(string.Format("{0}执行失败，RETCODE不为0\r", cmd));
            }
            return res;
        }

        public override string GetMTP2LNKAllList()
        {
            string cmd = "LST MTP2LNK:;";
            //cmd = "cat 'LST MTP2LNKALL.txt'";
            string res = getTC("MTP2LNK").ExecuteCmd(cmd, new string[] { "结果个数", "---    END" });
            CmdSuccess(cmd, res);
            if (!StringTools.CheckReturnCode(res))
            {
                throw new Exception(string.Format("{0}执行失败，RETCODE不为0\r", cmd));
            }

            return res;
        }


        public override string GetMTP2LNKList(int key)
        {
            string cmd = string.Format("LST MTP2LNK: LNKNO={0};", key);
            //cmd = "cat 'LST MTP2LNK.txt'";
            string res = getTC("MTP2LNK").ExecuteCmd(cmd, new string[] { "结果个数", "---    END" });
            CmdSuccess(cmd, res);
            if (!StringTools.CheckReturnCode(res))
            {
                throw new Exception(string.Format("{0}执行失败，RETCODE不为0\r", cmd));
            }
            return res;
        }

        public override string GetCLKSRCList()
        {
            string cmd = "LST CLKSRC:;";
            //cmd = "cat 'LST CLKSRC.txt'";
            string res = getTC("CLKSRC").ExecuteCmd(cmd, new string[] { "结果个数", "---    END" });
            CmdSuccess(cmd, res);
            if (!StringTools.CheckReturnCode(res))
            {
                throw new Exception(string.Format("{0}执行失败，RETCODE不为0\r", cmd));
            }
            return res;
        }

    }
}
